The following is your first chunk to start with. Remember, you can add chunks using the menu above (Insert -> R) or using the keyboard shortcut Ctrl+Alt+I. A good practice is to use different code chunks to answer different questions. You can delete this comment if you like.
Other useful keyboard shortcuts include Alt- for the assignment operator, and Ctrl+Shift+M for the pipe operator. You can delete these reminders if you don’t want them in your report.
Let’s first Load all the required libraries
#setwd("C:/GDrive/chingtea/BUDT758T2020/code/timeSeries/") #Don't forget to set your working directory before you start!
library("tidyverse")
library("fpp3")
[30m── [1mAttaching packages[22m ────────────────────────────────────────────────────────────────────────────── fpp3 0.2 ──[39m
[30m[32m✔[30m [34mtsibble [30m 0.8.6 [32m✔[30m [34mfeasts [30m 0.1.3
[32m✔[30m [34mtsibbledata[30m 0.1.0 [32m✔[30m [34mfable [30m 0.1.2[39m
[30m── [1mConflicts[22m ───────────────────────────────────────────────────────────────────────────────── fpp3_conflicts ──
[31m✖[30m [34mfabletools[30m::[32maccuracy()[30m masks [34myardstick[30m::accuracy()
[31m✖[30m [34mlubridate[30m::[32mdate()[30m masks [34mbase[30m::date()
[31m✖[30m [34mscales[30m::[32mdiscard()[30m masks [34mpurrr[30m::discard()
[31m✖[30m [34mplotly[30m::[32mfilter()[30m masks [34mdplyr[30m::filter(), [34mstats[30m::filter()
[31m✖[30m [34mfabletools[30m::[32mgenerate()[30m masks [34minfer[30m::generate()
[31m✖[30m [34mtsibble[30m::[32mid()[30m masks [34mdplyr[30m::id()
[31m✖[30m [34mtsibble[30m::[32minterval()[30m masks [34mlubridate[30m::interval()
[31m✖[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()
[31m✖[30m [34mcaret[30m::[32mlift()[30m masks [34mpurrr[30m::lift()
[31m✖[30m [34mfabletools[30m::[32mMAE()[30m masks [34mcaret[30m::MAE()
[31m✖[30m [34mdials[30m::[32mmargin()[30m masks [34mggplot2[30m::margin()
[31m✖[30m [34mtsibble[30m::[32mnew_interval()[30m masks [34mlubridate[30m::new_interval()
[31m✖[30m [34mfabletools[30m::[32mnull_model()[30m masks [34mparsnip[30m::null_model()
[31m✖[30m [34mfabletools[30m::[32mRMSE()[30m masks [34mcaret[30m::RMSE()[39m
library("plotly")
library("skimr")
library("lubridate")
tsDia <- read_csv('antidiabetic.csv')
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
X1 = [32mcol_double()[39m,
time = [32mcol_double()[39m,
value = [32mcol_double()[39m
)
Read the data
month <- as_tibble(yearmonth(seq(as.Date("1991-07-01"), as.Date("2008-06-01"), by = "1 month"))) %>%
rename(month=value)
tsDia <- read_csv('antidiabetic.csv') %>%
bind_cols(month) %>%
select(month, drugSales = value) %>%
as_tsibble(index = month)
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
X1 = [32mcol_double()[39m,
time = [32mcol_double()[39m,
value = [32mcol_double()[39m
)
Understanding time series data
Boston marathon
Trend without seasonality
tsBoston <-
boston_marathon %>%
filter(Event == "Men's open division") %>%
select(Year, Time) %>%
as_tsibble()
Winning times at the Boston Marathon
plotBoston <-
tsBoston %>%
autoplot() +
xlab("Year (yearly data)") + ylab("Time in HH:MM:SS") +
ggtitle("Winning times at the Boston Marathon (Men's open division)")
Plot variable not specified, automatically selected `.vars = Time`
ggplotly(plotBoston)
NA
Antidiabetic drug sales
Trend and seasonality are both evident
plotDia <-
tsDia %>%
autoplot() +
xlab("Year") + ylab("Total prescriptions ($ million)") +
ggtitle("Antidiabetic drug sales") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotDia)
Antidiabetic drug decomposed
Seasonal plot for antidiabetic drug sales
plotDiaSeason <-
tsDia %>%
gg_season(drugSales, labels = "both") +
xlab("Year") + ylab("Total prescriptions ($ million)") +
ggtitle("Antidiabetic drug sales")
plotDiaSeason
U.S. gasoline supplied
Both trend and seasonality
tsGas <-us_gasoline
U.S. finished motor gasoline product supplied
plotGas <-
tsGas %>%
autoplot() +
xlab("Year (weekly data)") + ylab("Million barrels per week") +
ggtitle("U.S. finished motor gasoline product supplied") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotGas)
U.S. gasoline supplied decomposed
plotGasDecomposed <-
tsGas %>%
model(STL(Barrels ~ trend() + season(window='periodic'), robust = TRUE)) %>%
components() %>%
autoplot() +
xlab("Year (weekly data)") + ylab("Million barrels per week") +
ggtitle("Seasonal and Trend decomposition using Loess (STL) for U.S. gasoline data") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotGasDecomposed)
plotGasDecomposed
U.S. retail employment Data
Trend overcomes seasonality
tsEmployment <-
us_employment %>%
filter(Title == "Retail Trade", Month >= '1980-01-01') %>%
select(Month, Employed)
U.S. retail employment
plotEmp <-
tsEmployment %>%
autoplot() +
xlab("Year (monthly data)") + ylab("Number of employed in retail (000)") +
ggtitle("U.S. retail employment data")
ggplotly(plotEmp)
U.S. retail employment decomposed
plotEmpDecomposed <-
tsEmployment %>%
model(STL(Employed ~ trend() + season(window='periodic'), robust = TRUE)) %>%
components() %>%
autoplot() +
xlab("Year (monthly data)") + ylab("Number of employed in retail (000)") +
ggtitle("Seasonal and Trend decomposition using Loess (STL) for U.S. retail employment data") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
plotEmpDecomposed
U.S. personal consumption expenditure data
Both trend and seasonality are weak
tsEcon <- us_change %>%
filter(Quarter >= '1980-01-01') %>%
select(Quarter, Consumption)
U.S. personal consumption
plotEcon <-
tsEcon %>%
autoplot() +
xlab("Year (quarterly data)") + ylab("Percentage changes in personal consumption") +
ggtitle("U.S. personal consumption expenditure data") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotEcon)
U.S. consumption decomposed
plotEconDecomposed <-
tsEcon %>%
model(STL(Consumption ~ trend() + season(window='periodic'), robust = TRUE)) %>%
components() %>%
autoplot() +
xlab("Year (quarterly data)") + ylab("Percentage changes in personal consumption") +
ggtitle("Seasonal and Trend decomposition using Loess (STL) for U.S. consumption data") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
plotEconDecomposed
Accidental deaths in the U.S.
Sesonality without trend
tsAcc <-
as_tsibble(USAccDeaths) %>%
rename(numOfAccDeaths = value)
Number of accidental deaths in the U.S.
plotAcc <-
tsAcc %>%
autoplot() +
xlab("Year") + ylab("Number of accidental deaths") +
ggtitle("Number of accidental deaths in the U.S.") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotAcc)
Accidental deaths decomposed
plotAcc <-
tsAcc %>%
model(STL(numOfAccDeaths ~ trend() + season(window='periodic'), robust = TRUE)) %>%
components() %>%
autoplot() +
xlab("Year (monthly data)") + ylab("Number of accidental deaths") +
ggtitle("Number of accidental deaths in the U.S.") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
plotAcc
Accidental deaths seasonal subseries
plotAccSub <-
tsAcc %>%
gg_subseries(numOfAccDeaths) +
ylab("Number of accidental deaths") +
xlab("Year (monthly data)") +
ggtitle("Seasonal subseries plot: Number of accidental deaths in the U.S.")
plotAccSub
Preliminary analysis of time series data
Autocorrelation function plot for the antidiabetic drug sales data
plotDiaACF <-
tsDia %>%
ACF(drugSales, lag_max = 48) %>%
autoplot() + ggtitle("Autocorrelation function (ACF) plot for the antidiabetic drug sales data")
plotDiaACF

Lag plots for the accidental deaths data
plotAccLag <-
tsAcc %>%
gg_lag(numOfAccDeaths, geom='point') +
xlab(NULL) + ylab(NULL) +
ggtitle("Lag plots for the accidental deaths data")
ggplotly(plotAccLag)
NA
Autocorrelation function (ACF) plot for the accidental deaths data
plotAccACF <-
tsAcc %>%
ACF(numOfAccDeaths, lag_max = 9) %>%
autoplot() + ggtitle("Autocorrelation function (ACF) plot for the accidental deaths data")
plotAccACF

Noise(randomly generated)
set.seed(333)
y <- tsibble(sample = 1:100, Noise = rnorm(100), index = sample)
y %>%
autoplot(Noise) + ggtitle("Noise over time") + xlab("Time")

Autocorrection for the noise
y %>%
ACF(Noise) %>% autoplot()
Additive vs. multiplicative decomposition
Remember antidiabetic drug sales?
plotDia <-
tsDia %>%
autoplot() +
xlab("Year") + ylab("Total prescriptions ($ million)") +
ggtitle("Antidiabetic drug sales") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotDia)
Additive decomposition
tsDia %>%
model(classical_decomposition(drugSales, type = "additive")) %>%
components() %>%
autoplot() +
xlab("Year") + ylab("Total prescriptions ($ million)") +
ggtitle("Classical additive decomposition of antidiabetic drug sales") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
Remember the STL decomposition?
plotDiaDecomposed <-
tsDia %>%
model(STL(drugSales ~ trend(window=10) + season(window='periodic'), robust = TRUE)) %>%
components() %>%
autoplot() +
xlab("Year") + ylab("Total prescriptions ($ million)") +
ggtitle("Seasonal and Trend decomposition using Loess (STL decomposition)") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
plotDiaDecomposed
Multiplicative decomposition
tsDia %>%
model(classical_decomposition(drugSales, type = "multiplicative")) %>%
components() %>%
autoplot() +
xlab("Year") + ylab("Total prescriptions ($ million)") +
ggtitle("Classical multiplicative decomposition of antidiabetic drug sales") +
scale_x_date(date_breaks = "years" , date_labels = "%y")
Decompose data without seasonality(STL)
plotBostonDecomposed <-
tsBoston %>%
mutate(Seconds = as.numeric(Time, units="seconds")) %>%
select(Year, Seconds) %>%
model(STL(Seconds ~ trend(), robust = TRUE)) %>%
components() %>%
autoplot() +
xlab("Year (yearly data)") + ylab("Time in seconds") +
ggtitle("Winning times at the Boston Marathon (Men's open division)")
plotBostonDecomposed
Removing seasonal variation(STL)
U.S. retail employment data Seasonally Adjusted
plotEmpSeasonallyAdjusted <-
tsEmployment %>%
autoplot(Employed, color='#A9A9B0') +
autolayer(components(tsEmployment %>% model(STL(Employed))), season_adjust, color='#1490D4') +
xlab("Year (monthly data)") + ylab("Number of employed in retail (000)") +
ggtitle("U.S. retail employment data")
ggplotly(plotEmpSeasonallyAdjusted)
us_employment %>%
filter(Title %in% c('Construction', 'Manufacturing', 'Leisure and Hospitality')) %>%
as_tsibble(key=Title) %>%
select(-Series_ID) %>%
features(Employed, feat_stl) %>%
rename_all(~str_remove(.x, '_year'))
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6CiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKYWx3YXlzX2FsbG93X2h0bWw6IHllcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKIyBUaGlzIGNodW5rIHNob3dzL2hpZGVzIHRoZSBjb2RlIGluIHlvdXIgZmluYWwgcmVwb3J0LiBXaGVuIGVjaG8gPSBUUlVFLCB0aGUgY29kZQojIGlzIHNob3duIGluIHRoZSByZXBvcnQuIFdoZW4gZWNobyA9IEZBTFNFLCB0aGUgY29kZSBpcyBoaWRkZW4gZnJvbSB0aGUgZmluYWwgcmVwb3J0LgojIFdlIHdvdWxkIGxpa2UgdG8gc2VlIHlvdXIgY29kZSwgc28gcGxlYXNlIGxlYXZlIHRoZSBzZXR0aW5nIGFzIGlzIGR1cmluZyB0aGUgY291cnNlLgojIFRoaXMgY2h1bmsgd2lsbCBub3Qgc2hvdyB1cCBpbiB5b3VyIHJlcG9ydHMsIHNvIHlvdSBjYW4gc2FmZWx5IGlnbm9yZSBpdHMgZXhpc3RlbmNlLgoKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKYGBgCgoKVGhlIGZvbGxvd2luZyBpcyB5b3VyIGZpcnN0IGNodW5rIHRvIHN0YXJ0IHdpdGguIFJlbWVtYmVyLCB5b3UgY2FuIGFkZCBjaHVua3MgdXNpbmcgdGhlIG1lbnUKYWJvdmUgKEluc2VydCAtPiBSKSBvciB1c2luZyB0aGUga2V5Ym9hcmQgc2hvcnRjdXQgQ3RybCtBbHQrSS4gQSBnb29kIHByYWN0aWNlIGlzIHRvIHVzZQpkaWZmZXJlbnQgY29kZSBjaHVua3MgdG8gYW5zd2VyIGRpZmZlcmVudCBxdWVzdGlvbnMuIFlvdSBjYW4gZGVsZXRlIHRoaXMgY29tbWVudCBpZiB5b3UgbGlrZS4KCk90aGVyIHVzZWZ1bCBrZXlib2FyZCBzaG9ydGN1dHMgaW5jbHVkZSBBbHQtIGZvciB0aGUgYXNzaWdubWVudCBvcGVyYXRvciwgYW5kIEN0cmwrU2hpZnQrTQpmb3IgdGhlIHBpcGUgb3BlcmF0b3IuIFlvdSBjYW4gZGVsZXRlIHRoZXNlIHJlbWluZGVycyBpZiB5b3UgZG9uJ3Qgd2FudCB0aGVtIGluIHlvdXIgcmVwb3J0LgoKKioqCgpMZXQncyBmaXJzdCBMb2FkIGFsbCB0aGUgcmVxdWlyZWQgbGlicmFyaWVzCmBgYHtyfQojc2V0d2QoIkM6L0dEcml2ZS9jaGluZ3RlYS9CVURUNzU4VDIwMjAvY29kZS90aW1lU2VyaWVzLyIpICNEb24ndCBmb3JnZXQgdG8gc2V0IHlvdXIgd29ya2luZyBkaXJlY3RvcnkgYmVmb3JlIHlvdSBzdGFydCEKCmxpYnJhcnkoInRpZHl2ZXJzZSIpCmxpYnJhcnkoImZwcDMiKQpsaWJyYXJ5KCJwbG90bHkiKQpsaWJyYXJ5KCJza2ltciIpCmxpYnJhcnkoImx1YnJpZGF0ZSIpCgpgYGAKYGBge3J9CnRzRGlhIDwtIHJlYWRfY3N2KCdhbnRpZGlhYmV0aWMuY3N2JykKYGBgCgoKUmVhZCB0aGUgZGF0YQpgYGB7cn0KbW9udGggPC0gYXNfdGliYmxlKHllYXJtb250aChzZXEoYXMuRGF0ZSgiMTk5MS0wNy0wMSIpLCBhcy5EYXRlKCIyMDA4LTA2LTAxIiksIGJ5ID0gIjEgbW9udGgiKSkpICU+JSAKICByZW5hbWUobW9udGg9dmFsdWUpCgoKdHNEaWEgPC0gcmVhZF9jc3YoJ2FudGlkaWFiZXRpYy5jc3YnKSAlPiUKICBiaW5kX2NvbHMobW9udGgpICU+JSAKICBzZWxlY3QobW9udGgsIGRydWdTYWxlcyA9IHZhbHVlKSAlPiUKICBhc190c2liYmxlKGluZGV4ID0gbW9udGgpCgpgYGAKCioqKgojIyBVbmRlcnN0YW5kaW5nIHRpbWUgc2VyaWVzIGRhdGEKCiMjIyBCb3N0b24gbWFyYXRob24KIyMjIyBUcmVuZCB3aXRob3V0IHNlYXNvbmFsaXR5CmBgYHtyfQp0c0Jvc3RvbiA8LQogIGJvc3Rvbl9tYXJhdGhvbiAlPiUgCiAgZmlsdGVyKEV2ZW50ID09ICJNZW4ncyBvcGVuIGRpdmlzaW9uIikgJT4lCiAgc2VsZWN0KFllYXIsIFRpbWUpICU+JQogIGFzX3RzaWJibGUoKQoKYGBgCgojIyMgV2lubmluZyB0aW1lcyBhdCB0aGUgQm9zdG9uIE1hcmF0aG9uCmBgYHtyfQpwbG90Qm9zdG9uIDwtCiAgdHNCb3N0b24gJT4lIAogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHllYXJseSBkYXRhKSIpICsgeWxhYigiVGltZSBpbiBISDpNTTpTUyIpICsKICBnZ3RpdGxlKCJXaW5uaW5nIHRpbWVzIGF0IHRoZSBCb3N0b24gTWFyYXRob24gKE1lbidzIG9wZW4gZGl2aXNpb24pIikKZ2dwbG90bHkocGxvdEJvc3RvbikKCmBgYAoKKioqCgojIyMgQW50aWRpYWJldGljIGRydWcgc2FsZXMKCiMjIyMgVHJlbmQgYW5kIHNlYXNvbmFsaXR5IGFyZSBib3RoIGV2aWRlbnQKYGBge3J9CnBsb3REaWEgPC0KICB0c0RpYSAlPiUgCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciIpICsgeWxhYigiVG90YWwgcHJlc2NyaXB0aW9ucyAoJCBtaWxsaW9uKSIpICsKICBnZ3RpdGxlKCJBbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RGlhKQoKYGBgCgoKCiMjIyBBbnRpZGlhYmV0aWMgZHJ1ZyBkZWNvbXBvc2VkCmBgYHtyfQpwbG90RGlhRGVjb21wb3NlZCA8LSAKICB0c0RpYSAlPiUKICBtb2RlbChTVEwoZHJ1Z1NhbGVzIH4gdHJlbmQod2luZG93PTEwKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUgCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIlRvdGFsIHByZXNjcmlwdGlvbnMgKCQgbWlsbGlvbikiKSArCiAgZ2d0aXRsZSgiU2Vhc29uYWwgYW5kIFRyZW5kIGRlY29tcG9zaXRpb24gdXNpbmcgTG9lc3MgKFNUTCBkZWNvbXBvc2l0aW9uKSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RGlhRGVjb21wb3NlZCkKCmBgYAoKCiMjIyBTZWFzb25hbCBwbG90IGZvciBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcwpgYGB7cn0KcGxvdERpYVNlYXNvbiA8LQogIHRzRGlhICU+JQogIGdnX3NlYXNvbihkcnVnU2FsZXMsIGxhYmVscyA9ICJib3RoIikgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIlRvdGFsIHByZXNjcmlwdGlvbnMgKCQgbWlsbGlvbikiKSArCiAgZ2d0aXRsZSgiQW50aWRpYWJldGljIGRydWcgc2FsZXMiKQpwbG90RGlhU2Vhc29uCgpgYGAKCioqKgoKIyMjICBVLlMuIGdhc29saW5lIHN1cHBsaWVkCiMjIyMgQm90aCB0cmVuZCBhbmQgc2Vhc29uYWxpdHkKCmBgYHtyfQp0c0dhcyA8LXVzX2dhc29saW5lCgpgYGAKClUuUy4gZmluaXNoZWQgbW90b3IgZ2Fzb2xpbmUgcHJvZHVjdCBzdXBwbGllZApgYGB7cn0KcGxvdEdhcyA8LQogIHRzR2FzICU+JSAKICBhdXRvcGxvdCgpICsKICB4bGFiKCJZZWFyICh3ZWVrbHkgZGF0YSkiKSArIHlsYWIoIk1pbGxpb24gYmFycmVscyBwZXIgd2VlayIpICsKICBnZ3RpdGxlKCJVLlMuIGZpbmlzaGVkIG1vdG9yIGdhc29saW5lIHByb2R1Y3Qgc3VwcGxpZWQiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKZ2dwbG90bHkocGxvdEdhcykKCmBgYAoKIyMjIFUuUy4gZ2Fzb2xpbmUgc3VwcGxpZWQgZGVjb21wb3NlZApgYGB7cn0KcGxvdEdhc0RlY29tcG9zZWQgPC0gCiAgdHNHYXMgJT4lCiAgbW9kZWwoU1RMKEJhcnJlbHMgfiB0cmVuZCgpICsgc2Vhc29uKHdpbmRvdz0ncGVyaW9kaWMnKSwgcm9idXN0ID0gVFJVRSkpICU+JSAKICBjb21wb25lbnRzKCkgJT4lCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciAod2Vla2x5IGRhdGEpIikgKyB5bGFiKCJNaWxsaW9uIGJhcnJlbHMgcGVyIHdlZWsiKSArCiAgZ2d0aXRsZSgiU2Vhc29uYWwgYW5kIFRyZW5kIGRlY29tcG9zaXRpb24gdXNpbmcgTG9lc3MgKFNUTCkgZm9yIFUuUy4gZ2Fzb2xpbmUgZGF0YSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90R2FzRGVjb21wb3NlZCkKcGxvdEdhc0RlY29tcG9zZWQKYGBgCgoqKioKCiMjIyBVLlMuIHJldGFpbCBlbXBsb3ltZW50IERhdGEKIyMjIyBUcmVuZCBvdmVyY29tZXMgc2Vhc29uYWxpdHkKCmBgYHtyfQp0c0VtcGxveW1lbnQgPC0KICB1c19lbXBsb3ltZW50ICU+JSAKICBmaWx0ZXIoVGl0bGUgPT0gIlJldGFpbCBUcmFkZSIsIE1vbnRoID49ICcxOTgwLTAxLTAxJykgJT4lCiAgc2VsZWN0KE1vbnRoLCBFbXBsb3llZCkKCmBgYAoKIyMjIyBVLlMuIHJldGFpbCBlbXBsb3ltZW50CmBgYHtyfQpwbG90RW1wIDwtCiAgdHNFbXBsb3ltZW50ICU+JSAKICBhdXRvcGxvdCgpICsKICB4bGFiKCJZZWFyIChtb250aGx5IGRhdGEpIikgKyB5bGFiKCJOdW1iZXIgb2YgZW1wbG95ZWQgaW4gcmV0YWlsICgwMDApIikgKwogIGdndGl0bGUoIlUuUy4gcmV0YWlsIGVtcGxveW1lbnQgZGF0YSIpCmdncGxvdGx5KHBsb3RFbXApCgpgYGAKCgojIyMgVS5TLiByZXRhaWwgZW1wbG95bWVudCBkZWNvbXBvc2VkCmBgYHtyfQpwbG90RW1wRGVjb21wb3NlZCA8LSAKICB0c0VtcGxveW1lbnQgJT4lCiAgbW9kZWwoU1RMKEVtcGxveWVkIH4gdHJlbmQoKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUgCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKG1vbnRobHkgZGF0YSkiKSArIHlsYWIoIk51bWJlciBvZiBlbXBsb3llZCBpbiByZXRhaWwgKDAwMCkiKSArCiAgZ2d0aXRsZSgiU2Vhc29uYWwgYW5kIFRyZW5kIGRlY29tcG9zaXRpb24gdXNpbmcgTG9lc3MgKFNUTCkgZm9yIFUuUy4gcmV0YWlsIGVtcGxveW1lbnQgZGF0YSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpwbG90RW1wRGVjb21wb3NlZAoKYGBgCgoqKioKCiMjIyBVLlMuIHBlcnNvbmFsIGNvbnN1bXB0aW9uIGV4cGVuZGl0dXJlIGRhdGEKIyMjIyBCb3RoIHRyZW5kIGFuZCBzZWFzb25hbGl0eSBhcmUgd2VhawpgYGB7cn0KdHNFY29uIDwtIHVzX2NoYW5nZSAlPiUgCiAgZmlsdGVyKFF1YXJ0ZXIgPj0gJzE5ODAtMDEtMDEnKSAlPiUKICBzZWxlY3QoUXVhcnRlciwgQ29uc3VtcHRpb24pCgpgYGAKCiMjIyMgVS5TLiBwZXJzb25hbCBjb25zdW1wdGlvbgpgYGB7cn0KcGxvdEVjb24gPC0KICB0c0Vjb24gJT4lIAogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHF1YXJ0ZXJseSBkYXRhKSIpICsgeWxhYigiUGVyY2VudGFnZSBjaGFuZ2VzIGluIHBlcnNvbmFsIGNvbnN1bXB0aW9uIikgKwogIGdndGl0bGUoIlUuUy4gcGVyc29uYWwgY29uc3VtcHRpb24gZXhwZW5kaXR1cmUgZGF0YSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RWNvbikKCmBgYAoKIyMjIyBVLlMuIGNvbnN1bXB0aW9uIGRlY29tcG9zZWQKYGBge3J9CnBsb3RFY29uRGVjb21wb3NlZCA8LSAKICB0c0Vjb24gJT4lCiAgbW9kZWwoU1RMKENvbnN1bXB0aW9uIH4gdHJlbmQoKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUgCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHF1YXJ0ZXJseSBkYXRhKSIpICsgeWxhYigiUGVyY2VudGFnZSBjaGFuZ2VzIGluIHBlcnNvbmFsIGNvbnN1bXB0aW9uIikgKwogIGdndGl0bGUoIlNlYXNvbmFsIGFuZCBUcmVuZCBkZWNvbXBvc2l0aW9uIHVzaW5nIExvZXNzIChTVEwpIGZvciBVLlMuIGNvbnN1bXB0aW9uIGRhdGEiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKcGxvdEVjb25EZWNvbXBvc2VkCgpgYGAKCioqKgoKIyMjIEFjY2lkZW50YWwgZGVhdGhzIGluIHRoZSBVLlMuCiMjIyMgU2Vzb25hbGl0eSB3aXRob3V0IHRyZW5kCmBgYHtyfQp0c0FjYyA8LQogIGFzX3RzaWJibGUoVVNBY2NEZWF0aHMpICU+JSAKICByZW5hbWUobnVtT2ZBY2NEZWF0aHMgPSB2YWx1ZSkKCmBgYAoKTnVtYmVyIG9mIGFjY2lkZW50YWwgZGVhdGhzIGluIHRoZSBVLlMuCmBgYHtyfQpwbG90QWNjIDwtCiAgdHNBY2MgJT4lIAogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIk51bWJlciBvZiBhY2NpZGVudGFsIGRlYXRocyIpICsKICBnZ3RpdGxlKCJOdW1iZXIgb2YgYWNjaWRlbnRhbCBkZWF0aHMgaW4gdGhlIFUuUy4iKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKZ2dwbG90bHkocGxvdEFjYykKCmBgYAoKIyMjIyBBY2NpZGVudGFsIGRlYXRocyBkZWNvbXBvc2VkCmBgYHtyfQpwbG90QWNjIDwtIAogIHRzQWNjICU+JQogIG1vZGVsKFNUTChudW1PZkFjY0RlYXRocyB+IHRyZW5kKCkgKyBzZWFzb24od2luZG93PSdwZXJpb2RpYycpLCByb2J1c3QgPSBUUlVFKSkgJT4lCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKG1vbnRobHkgZGF0YSkiKSArIHlsYWIoIk51bWJlciBvZiBhY2NpZGVudGFsIGRlYXRocyIpICsKICBnZ3RpdGxlKCJOdW1iZXIgb2YgYWNjaWRlbnRhbCBkZWF0aHMgaW4gdGhlIFUuUy4iKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKcGxvdEFjYwoKYGBgCgojIyMgQWNjaWRlbnRhbCBkZWF0aHMgc2Vhc29uYWwgc3Vic2VyaWVzCmBgYHtyfQpwbG90QWNjU3ViIDwtIAogIHRzQWNjICU+JSAKICBnZ19zdWJzZXJpZXMobnVtT2ZBY2NEZWF0aHMpICsKICB5bGFiKCJOdW1iZXIgb2YgYWNjaWRlbnRhbCBkZWF0aHMiKSArCiAgeGxhYigiWWVhciAobW9udGhseSBkYXRhKSIpICsKICBnZ3RpdGxlKCJTZWFzb25hbCBzdWJzZXJpZXMgcGxvdDogTnVtYmVyIG9mIGFjY2lkZW50YWwgZGVhdGhzIGluIHRoZSBVLlMuIikKcGxvdEFjY1N1YgoKYGBgCgoqKioKIyMgUHJlbGltaW5hcnkgYW5hbHlzaXMgb2YgdGltZSBzZXJpZXMgZGF0YQoKIyMjIyBBdXRvY29ycmVsYXRpb24gZnVuY3Rpb24gcGxvdCBmb3IgdGhlIGFudGlkaWFiZXRpYyBkcnVnIHNhbGVzIGRhdGEKYGBge3J9CnBsb3REaWFBQ0YgPC0KICB0c0RpYSAlPiUKICBBQ0YoZHJ1Z1NhbGVzLCBsYWdfbWF4ID0gNDgpICU+JQogIGF1dG9wbG90KCkgKyAgZ2d0aXRsZSgiQXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uIChBQ0YpIHBsb3QgZm9yIHRoZSBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyBkYXRhIikKcGxvdERpYUFDRgoKYGBgCgojIyMgTGFnIHBsb3RzIGZvciB0aGUgYWNjaWRlbnRhbCBkZWF0aHMgZGF0YQpgYGB7cn0KcGxvdEFjY0xhZyA8LQogIHRzQWNjICU+JQogIGdnX2xhZyhudW1PZkFjY0RlYXRocywgZ2VvbT0ncG9pbnQnKSArCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKwogIGdndGl0bGUoIkxhZyBwbG90cyBmb3IgdGhlIGFjY2lkZW50YWwgZGVhdGhzIGRhdGEiKQpnZ3Bsb3RseShwbG90QWNjTGFnKQoKYGBgCgojIyMgQXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uIChBQ0YpIHBsb3QgZm9yIHRoZSBhY2NpZGVudGFsIGRlYXRocyBkYXRhCmBgYHtyfQpwbG90QWNjQUNGIDwtCiAgdHNBY2MgJT4lCiAgQUNGKG51bU9mQWNjRGVhdGhzLCBsYWdfbWF4ID0gOSkgJT4lCiAgYXV0b3Bsb3QoKSArICBnZ3RpdGxlKCJBdXRvY29ycmVsYXRpb24gZnVuY3Rpb24gKEFDRikgcGxvdCBmb3IgdGhlIGFjY2lkZW50YWwgZGVhdGhzIGRhdGEiKQpwbG90QWNjQUNGCgpgYGAKCgoKIyMjIE5vaXNlKHJhbmRvbWx5IGdlbmVyYXRlZCkKYGBge3J9CnNldC5zZWVkKDMzMykKeSA8LSB0c2liYmxlKHNhbXBsZSA9IDE6MTAwLCBOb2lzZSA9IHJub3JtKDEwMCksIGluZGV4ID0gc2FtcGxlKQp5ICU+JQogIGF1dG9wbG90KE5vaXNlKSArIGdndGl0bGUoIk5vaXNlIG92ZXIgdGltZSIpICsgeGxhYigiVGltZSIpCgpgYGAKCiMjIyBBdXRvY29ycmVjdGlvbiBmb3IgdGhlIG5vaXNlCmBgYHtyfQp5ICU+JQogIEFDRihOb2lzZSkgJT4lIGF1dG9wbG90KCkKCmBgYAoKIyMjIEFkZGl0aXZlIHZzLiBtdWx0aXBsaWNhdGl2ZSBkZWNvbXBvc2l0aW9uCiMjIyBSZW1lbWJlciBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcz8KYGBge3J9CnBsb3REaWEgPC0KICB0c0RpYSAlPiUgCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciIpICsgeWxhYigiVG90YWwgcHJlc2NyaXB0aW9ucyAoJCBtaWxsaW9uKSIpICsKICBnZ3RpdGxlKCJBbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RGlhKQoKYGBgCgojIyMgQWRkaXRpdmUgZGVjb21wb3NpdGlvbgpgYGB7cn0KdHNEaWEgJT4lIAogIG1vZGVsKGNsYXNzaWNhbF9kZWNvbXBvc2l0aW9uKGRydWdTYWxlcywgdHlwZSA9ICJhZGRpdGl2ZSIpKSAlPiUKICBjb21wb25lbnRzKCkgJT4lCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciIpICsgeWxhYigiVG90YWwgcHJlc2NyaXB0aW9ucyAoJCBtaWxsaW9uKSIpICsKICBnZ3RpdGxlKCJDbGFzc2ljYWwgYWRkaXRpdmUgZGVjb21wb3NpdGlvbiBvZiBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQoKYGBgCgojIyMgUmVtZW1iZXIgdGhlIFNUTCBkZWNvbXBvc2l0aW9uPwpgYGB7cn0KcGxvdERpYURlY29tcG9zZWQgPC0gCiAgdHNEaWEgJT4lCiAgbW9kZWwoU1RMKGRydWdTYWxlcyB+IHRyZW5kKHdpbmRvdz0xMCkgKyBzZWFzb24od2luZG93PSdwZXJpb2RpYycpLCByb2J1c3QgPSBUUlVFKSkgJT4lIAogIGNvbXBvbmVudHMoKSAlPiUKICBhdXRvcGxvdCgpICsKICB4bGFiKCJZZWFyIikgKyB5bGFiKCJUb3RhbCBwcmVzY3JpcHRpb25zICgkIG1pbGxpb24pIikgKwogIGdndGl0bGUoIlNlYXNvbmFsIGFuZCBUcmVuZCBkZWNvbXBvc2l0aW9uIHVzaW5nIExvZXNzIChTVEwgZGVjb21wb3NpdGlvbikiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKcGxvdERpYURlY29tcG9zZWQKCmBgYAoKIyMjIE11bHRpcGxpY2F0aXZlIGRlY29tcG9zaXRpb24KYGBge3J9CnRzRGlhICU+JSAKICBtb2RlbChjbGFzc2ljYWxfZGVjb21wb3NpdGlvbihkcnVnU2FsZXMsIHR5cGUgPSAibXVsdGlwbGljYXRpdmUiKSkgJT4lCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIlRvdGFsIHByZXNjcmlwdGlvbnMgKCQgbWlsbGlvbikiKSArCiAgZ2d0aXRsZSgiQ2xhc3NpY2FsIG11bHRpcGxpY2F0aXZlIGRlY29tcG9zaXRpb24gb2YgYW50aWRpYWJldGljIGRydWcgc2FsZXMiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKCmBgYAoKKioqCgojIyMgRGVjb21wb3NlIGRhdGEgd2l0aG91dCBzZWFzb25hbGl0eShTVEwpCmBgYHtyfQpwbG90Qm9zdG9uRGVjb21wb3NlZCA8LQogIHRzQm9zdG9uICU+JQogIG11dGF0ZShTZWNvbmRzID0gYXMubnVtZXJpYyhUaW1lLCB1bml0cz0ic2Vjb25kcyIpKSAlPiUKICBzZWxlY3QoWWVhciwgU2Vjb25kcykgJT4lCiAgbW9kZWwoU1RMKFNlY29uZHMgfiB0cmVuZCgpLCByb2J1c3QgPSBUUlVFKSkgJT4lCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHllYXJseSBkYXRhKSIpICsgeWxhYigiVGltZSBpbiBzZWNvbmRzIikgKwogIGdndGl0bGUoIldpbm5pbmcgdGltZXMgYXQgdGhlIEJvc3RvbiBNYXJhdGhvbiAoTWVuJ3Mgb3BlbiBkaXZpc2lvbikiKQpwbG90Qm9zdG9uRGVjb21wb3NlZAoKYGBgCgojIyMgUmVtb3Zpbmcgc2Vhc29uYWwgdmFyaWF0aW9uKFNUTCkKIyMjIFUuUy4gcmV0YWlsIGVtcGxveW1lbnQgZGF0YSBTZWFzb25hbGx5IEFkanVzdGVkCmBgYHtyfQpwbG90RW1wU2Vhc29uYWxseUFkanVzdGVkIDwtCiAgdHNFbXBsb3ltZW50ICU+JQogIGF1dG9wbG90KEVtcGxveWVkLCBjb2xvcj0nI0E5QTlCMCcpICsKICBhdXRvbGF5ZXIoY29tcG9uZW50cyh0c0VtcGxveW1lbnQgJT4lIG1vZGVsKFNUTChFbXBsb3llZCkpKSwgc2Vhc29uX2FkanVzdCwgY29sb3I9JyMxNDkwRDQnKSArCiAgeGxhYigiWWVhciAobW9udGhseSBkYXRhKSIpICsgeWxhYigiTnVtYmVyIG9mIGVtcGxveWVkIGluIHJldGFpbCAoMDAwKSIpICsKICBnZ3RpdGxlKCJVLlMuIHJldGFpbCBlbXBsb3ltZW50IGRhdGEiKQpnZ3Bsb3RseShwbG90RW1wU2Vhc29uYWxseUFkanVzdGVkKQoKYGBgCgpgYGB7cn0KdXNfZW1wbG95bWVudCAlPiUKICBmaWx0ZXIoVGl0bGUgJWluJSBjKCdDb25zdHJ1Y3Rpb24nLCAnTWFudWZhY3R1cmluZycsICdMZWlzdXJlIGFuZCBIb3NwaXRhbGl0eScpKSAlPiUgCiAgYXNfdHNpYmJsZShrZXk9VGl0bGUpICU+JQogIHNlbGVjdCgtU2VyaWVzX0lEKSAlPiUgCiAgZmVhdHVyZXMoRW1wbG95ZWQsIGZlYXRfc3RsKSAlPiUgCiAgcmVuYW1lX2FsbCh+c3RyX3JlbW92ZSgueCwgJ195ZWFyJykpCgpgYGAKCg==